package com.snda.sng.chat
{
	import com.snda.sng.chat.events.ChatClientErrorEvent;
	import com.snda.sng.chat.events.ChatClientMessageEvent;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import flash.utils.Timer;
	
	/**
	 * ChatClient
	 * @author 任冬 rending01@snda.com
	 * $Id: ChatClient.as 28 2011-07-22 02:59:01Z rendong $
	 * @version 1.0
	 */
	public class ChatClient extends EventDispatcher
	{
		/**
		 * 世界聊天频道 
		 */		
		public static const CHANNEL_WORLD:String = "world";
		
		private var UserID:String;
		private var UserName:String;
		
		private var password:String;
		private var host:String;
		private var port:int;
		
		private var friends:Vector.<String>;
		
		private var conn:ChatConnection;
		
		private var userErrorHandler:Function;
		
		/**
		 * 消息事件，通过MsgType区分消息 
		 */		
		[Event(name="ChatClientMessageEvent",type="com.snda.sng.chat.events.ChatClientMessageEvent")]
		
		/**
		 * 错误事件，通过errorType区分消息 
		 */		
		[Event(name="ChatClientErrorEvent",type="com.snda.sng.chat.events.ChatClientErrorEvent")]
		
		/**
		 * 初始化 
		 * @param UserID
		 * @param UserName
		 * 
		 */		
		public function ChatClient(UserID:String, UserName:String, password:String, host:String, port:int)
		{
			this.UserID = UserID;
			this.UserName = UserName;
			
			this.password = password;
			this.host = host;
			this.port = port;
			
			this.friends = new Vector.<String>();
		}
		
		/**
		 * 添加好友uid 
		 * @param FUserID
		 * 
		 */		
		public function addFriendID(FUserID:String):void
		{
			if (conn != null)
				throw new ArgumentError("addFriendID Must Before connect Invoke!");
			
			this.friends.push(FUserID);
		}
		
		/**
		 * 连接服务器 
		 * 
		 */		
		public function connect():void
		{
			conn = new ChatConnection(packHandler);
			conn.addEventListener(Event.CONNECT, connectHandler);
			conn.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			conn.addEventListener(SecurityErrorEvent.SECURITY_ERROR, sErrorHandler);
			conn.addEventListener(Event.CLOSE, ioErrorHandler);
			conn.connect(host, port);
		}
		
		// 错误
		private function ioErrorHandler(e:Event):void
		{
			var event:ChatClientErrorEvent = new ChatClientErrorEvent(ChatClientErrorEvent.EventType);
			event.errorType = ChatClientErrorEvent.ERROR_IOERROR;
			var t:Timer = new Timer(1500, 1);
			t.addEventListener(TimerEvent.TIMER_COMPLETE, reConnectHandler);
			t.start();
			
			dispatchEvent(event);
		}
		
		// 断线重连
		private function reConnectHandler(e:TimerEvent):void
		{
			var t:Timer = e.currentTarget as Timer;
			t.removeEventListener(TimerEvent.TIMER_COMPLETE, reConnectHandler);
			
			if (!conn.connected)
				conn.connect(host, port);
		}
		
		// 错误
		private function sErrorHandler(e:Event):void
		{
			var event:ChatClientErrorEvent = new ChatClientErrorEvent(ChatClientErrorEvent.EventType);
			event.errorType = ChatClientErrorEvent.ERROR_SECURITY;
			
			dispatchEvent(event);
		}
		
		// 连接成功，发送认证命令
		private function connectHandler(e:Event):void
		{
			var msg:ByteArray = new ByteArray();
			msg.endian = Endian.LITTLE_ENDIAN;
			
			msg.position = 4;
			msg.writeShort(100);
			
			ChatUtil.writeString(msg, UserID);
			ChatUtil.writeString(msg, UserName);
			ChatUtil.writeString(msg, password);
			msg.position = 0;
			
			msg.writeInt(msg.length - 4);
			
			conn.writeBytes(msg, 0, 0);
			conn.flush();
			msg.clear();
		}
		
		/**
		 * 加入聊天频道，如公会 
		 * @param ChannelName
		 * 
		 */
		public function addChannel(ChannelName:String):void
		{
			var msg:ByteArray = new ByteArray();
			msg.endian = Endian.LITTLE_ENDIAN;
			
			msg.position = 4;
			msg.writeShort(102);
			
			ChatUtil.writeString(msg, ChannelName);
			msg.position = 0;
			
			msg.writeInt(msg.length - 4);
			
			conn.writeBytes(msg, 0, 0);
			conn.flush();
			msg.clear();
		}
		
		/**
		 * 发送频道聊天 
		 * @param ChannelName	频道名称
		 * @param msg
		 * 
		 */		
		public function sendChannelMsg(ChannelName:String, msg:String):void
		{
			sendChatMsg(103, ChannelName, msg);
		}
		
		/**
		 * 发送私聊信息 
		 * @param ToFriendUserID 目标用户编号
		 * @param msg
		 * 
		 */		
		public function sendPrivateMsg(ToFriendUserID:String, msg:String):void
		{
			sendChatMsg(104, ToFriendUserID, msg);
		}
		
		/**
		 * 发送聊天信息
		 *  
		 * @param type
		 * @param name
		 * @param msg
		 * 
		 */		
		private function sendChatMsg(type:int, name:String, message:String):void
		{
			var msg:ByteArray = new ByteArray();
			msg.endian = Endian.LITTLE_ENDIAN;
			
			msg.position = 4;
			msg.writeShort(type);
			
			ChatUtil.writeString(msg, name);
			ChatUtil.writeString(msg, ChatUtil.filter(message));
			msg.position = 0;
			
			msg.writeInt(msg.length - 4);
			
			if (conn.connected)
			{
				conn.writeBytes(msg, 0, 0);
				conn.flush();
			}
			msg.clear();
		}
		
		/**
		 * 关闭连接 
		 * 
		 */		
		public function close():void
		{
			conn.close();
		}
		
		/**
		 * 包处理函数 
		 * @param type
		 * @param len
		 * @param message
		 * 
		 */		
		private function packHandler(type:int, len:int, message:ByteArray):void
		{
			switch(type)
			{
				case ChatClientMessageEvent.TYPE_Auth:
					ServerAuthPack(type, len, message);
					break;
				case ChatClientMessageEvent.TYPE_Friend_Online_List:
					ServerOnlineFriends(type, len, message);
					break;
				case ChatClientMessageEvent.TYPE_Friend_Status_Online:
				case ChatClientMessageEvent.TYPE_Friend_Status_Offline:
					ServerFriendStatus(type, len, message);
					break;
				case ChatClientMessageEvent.TYPE_Channel_Success:
				case ChatClientMessageEvent.TYPE_Channel_Fail:
					ServerChannelResult(type, len ,message);
					break;
				case ChatClientMessageEvent.TYPE_Msg_Channel:
				case ChatClientMessageEvent.TYPE_Msg_Private:
				case ChatClientMessageEvent.TYPE_Msg_Admin:
					ServerChatMessage(type, len, message);
					break;
			}
		}
		
		// 聊天消息
		private function ServerChatMessage(type:int, len:int, message:ByteArray):void
		{
			var event:ChatClientMessageEvent = new ChatClientMessageEvent(ChatClientMessageEvent.EventType);
			event.MsgType = type;
			
			event.srcUserID = ChatUtil.readString(message);
			event.srcUserName = ChatUtil.readString(message);
			event.Name = ChatUtil.readString(message);
			event.Message = ChatUtil.readString(message);
			
			dispatchEvent(event);
		}
		
		// 加入频道返回
		private function ServerChannelResult(type:int, len:int, message:ByteArray):void
		{
			var event:ChatClientMessageEvent = new ChatClientMessageEvent(ChatClientMessageEvent.EventType);
			event.MsgType = type;
			
			event.ChannelName = ChatUtil.readString(message);
			dispatchEvent(event);
		}
		
		/**
		 * 好友状态切换 
		 * @param type
		 * @param len
		 * @param message
		 * 
		 */		
		private function ServerFriendStatus(type:int, len:int, message:ByteArray):void
		{
			var event:ChatClientMessageEvent = new ChatClientMessageEvent(ChatClientMessageEvent.EventType);
			event.MsgType = type;
			
			event.FriendID = ChatUtil.readString(message);
			dispatchEvent(event);
		}
		
		// 用户在线
		private function ServerOnlineFriends(type:int, len:int, message:ByteArray):void
		{
			var friendLength:int = message.readInt();
			var friends:Vector.<String> = new Vector.<String>();
			
			for(var i:int = 0; i<friendLength; i++)
			{
				friends.push(ChatUtil.readString(message));
			}
			
			var event:ChatClientMessageEvent = new ChatClientMessageEvent(ChatClientMessageEvent.EventType);
			event.MsgType = type;
			event.onlineFriendsList = friends;
			dispatchEvent(event);
		}
		
		// 认证消息处理
		private function ServerAuthPack(type:int, len:int, message:ByteArray):void
		{
			var status:int = message.readInt();
			if (status == 1){
				var event:ChatClientMessageEvent = new ChatClientMessageEvent(ChatClientMessageEvent.EventType);
				event.MsgType = type;
				dispatchEvent(event);
				
				// 查询好友状态
				if (friends.length > 0)
				{
					var msg:ByteArray = new ByteArray();
					msg.endian = Endian.LITTLE_ENDIAN;
					
					msg.position = 4;
					msg.writeShort(101);
					//len+type+friendLength+[friendid,friendid...friendid]
				//	长度+类型+在线好友数量+在线好友id列表
					msg.writeInt(friends.length);
					
					for(var i:int = 0; i<friends.length; i++){
						var fid:String = friends[i];
						ChatUtil.writeString(msg, fid);
					}
					
					msg.position = 0;
					
					msg.writeInt(msg.length - 4);
					
					conn.writeBytes(msg, 0, 0);
					conn.flush();
					msg.clear();
				}
			}else{
				var errorEvent:ChatClientErrorEvent = new ChatClientErrorEvent(ChatClientErrorEvent.EventType);
				errorEvent.errorType = ChatClientErrorEvent.ERROR_AUTH_FAIL;
				
				dispatchEvent(errorEvent);
			}
		}
	}
}
